package com.the_ring.chapter11.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

public class MultiTouchView extends View {

    private Paint mPathPaint = new Paint();
    private Paint mBeginPaint = new Paint();
    private Paint mEndPaint = new Paint();

    private Path mFirstPath = new Path();       // 声明主要动作的路径对象
    private Path mSecondPath = new Path();      // 声明次要动作的路径对象
    private PointF mFirstLastP, mFirstBeginP, mFirstEndP;
    private PointF mSecondLastP, mSecondBeginP, mSecondEndP;
    private boolean isFinish = false;           // 收否结束触摸

    public MultiTouchView(Context context) {
        this(context, null);
    }

    public MultiTouchView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mPathPaint.setColor(Color.BLACK);
        mBeginPaint.setColor(Color.RED);
        mEndPaint.setColor(Color.GREEN);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawPath(mFirstPath, mPathPaint);            // 在画布上按指定路径绘制线条
        canvas.drawPath(mSecondPath, mPathPaint);           // 在画布上按指定路径绘制线条
        if (isFinish) {                     // 护额事宜触摸，则绘制两个起点的连线以及两个终点的连线
            if (mFirstBeginP != null && mSecondBeginP != null) {    // 绘制两个起点的连线
                canvas.drawLine(mFirstBeginP.x, mFirstBeginP.y, mSecondBeginP.x, mSecondBeginP.y, mBeginPaint);
            }
            if (mFirstEndP != null && mSecondEndP != null) {    // 绘制两个终点的连线
                canvas.drawLine(mFirstEndP.x, mFirstEndP.y, mSecondEndP.x, mSecondEndP.y, mEndPaint);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        PointF firstP = new PointF(event.getX(), event.getY());
        PointF secondP = null;
        if (event.getPointerCount() >= 2) {         // 存在多点触摸
            secondP = new PointF(event.getX(1), event.getY(1));
        }
        int action = event.getAction() & MotionEvent.ACTION_MASK;
        if (action == MotionEvent.ACTION_DOWN) {        // 主要点按下
            isFinish = false;
            mFirstPath.reset();
            mSecondPath.reset();
            mFirstPath.moveTo(firstP.x, firstP.y);      // 移动到指定坐标点
            mFirstBeginP = new PointF(firstP.x, firstP.y);
            mFirstEndP = null;
        } else if (action == MotionEvent.ACTION_MOVE) {     // 移动手指
            if (!isFinish) {
                mFirstPath.quadTo(mFirstLastP.x, mFirstLastP.y, firstP.x, firstP.y);
                if (secondP != null) {
                    mSecondPath.quadTo(mSecondLastP.x, mSecondLastP.y, secondP.x, secondP.y);
                }
            }
        } else if (action == MotionEvent.ACTION_UP) {               // 主要点松开
        } else if (action == MotionEvent.ACTION_POINTER_DOWN) {     // 次要点按下
            mSecondPath.moveTo(secondP.x, secondP.y);               // 移动到指定坐标点
            mSecondBeginP = new PointF(secondP.x, secondP.y);
            mSecondEndP = null;
        } else if (action == MotionEvent.ACTION_POINTER_UP) {       // 次要点松开
            isFinish = true;
            mFirstEndP = new PointF(firstP.x, firstP.y);
            mSecondEndP = new PointF(secondP.x, secondP.y);
            if (mListener != null) {        // 触发手势滑动动作
                mListener.onSlideFinish(mFirstBeginP, mFirstEndP, mSecondBeginP, mSecondEndP);
            }
        }
        mFirstLastP = new PointF(firstP.x, firstP.y);
        if (secondP != null) {
            mSecondLastP = new PointF(secondP.x, secondP.y);
        }
        postInvalidate();           // 立即刷新视图（线程安全方式）
        return true;
    }

    private SlideListener mListener;

    public void setListener(SlideListener mListener) {
        this.mListener = mListener;
    }

    public interface SlideListener {
        void onSlideFinish(PointF firstBeginP, PointF firstEndP, PointF secondBeginP, PointF secondEndP);
        /**
         * // 上次两个触摸点之间的距离
         * float preWholeDistance = PointUtil.distance(firstBeginP, secondBeginP);
         * // 当前两个触摸点之间的距离
         * float nowWholeDistance = PointUtil.distance(firstEndP, secondEndP);
         * // 主要点在前后两次落点之间的距离
         * float primaryDistance = PointUtil.distance(firstBeginP, firstEndP);
         * // 次要点在前后两次落点之间的距离
         * float secondaryDistance = PointUtil.distance(secondBeginP, secondEndP);
         * if (Math.abs(nowWholeDistance - preWholeDistance) > (float) Math.sqrt(2) / 2.0f * (primaryDistance + secondaryDistance)) {
         *     // 倾向于在原始线段的相同方向上移动，则判作缩放动作
         *     float scaleRatio = nowWholeDistance / preWholeDistance;
         *     scaleRatio >= 1 ? "放大" : "缩小"
         * } else {
         *     // 倾向于在原始线段的相同方向上移动，则判作旋转动作
         *     // 计算上次触摸事件的旋转角度
         *     int preDegree = PointUtil.degree(firstBeginP, secondBeginP);
         *     // 计算本次触摸事件的旋转角度
         *     int nowDegree = PointUtil.degree(firstEndP, secondEndP);
         *     nowDegree > preDegree ? "顺时针" : "逆时针"
         *     角度 Math.abs(nowDegree - preDegree)
         * }
         */
    }
}
